package com.teamwings.modules.buffet.controller;

import com.teamwings.util.RedisUtil;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.file.api.feign.FileServiceFeign;
import org.jeecg.common.loader.DeployLoader;
import org.jeecg.common.util.CommonUtil;
import org.jeecg.common.util.PathUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

@RequestMapping("/form/hot")
@RestController
public class DeployController {

	@Autowired
	private FileServiceFeign fileServiceFeign;

	@Autowired
	private RedisUtil redisUtil;


	@RequestMapping("/exec/{clzName}/{method}")
	public Result<?> exec(
			@PathVariable("clzName") String clzName,
			@PathVariable("method") String method,
			HttpServletRequest request,
			HttpServletResponse response) {
		String clzFullName = "hot.form." + clzName;
		String clzRedisName = "hot:form:" + clzName;
		DeployLoader loader = DeployLoader.getInstance();
		String clzSize = redisUtil.get(clzRedisName);
		try {
			Class<?> clazz = loader.getClass(clzFullName);
			// 存在则已编译并加载
			if (clazz != null) {
				// redis中，其他开发人员上传并编译后class的长度，与当前个人中已有的byte[]数据对比
				int clzLength = CommonUtil.CLASS_BYTES.get(clzFullName).length;
				// 缓存信息为空，或者 缓存信息与之大小不相等(即已过时)，需要重新下载编译并设置缓存
				if (StringUtils.isBlank(clzSize) || clzLength != Integer.parseInt(clzSize)) {
					// 暂时默认文件服务中存在该文件，下载保存默认成功
					CommonUtil.downloadFileToLocal(clzFullName);
					// 同一个加载器不能多次加载同一个类，否则报attempted  duplicate class definition for name ，需要new一个loader
					loader = DeployLoader.getInstance();
					// 进行编译
					loader.compiler(clzFullName);
					// 设置缓存
					redisUtil.set(clzRedisName, String.valueOf(CommonUtil.CLASS_BYTES.get(clzFullName).length));
					// 类加载
					clazz = loader.getClass(clzFullName);
				}
			} else {
				// 不存在，即未编译，需要重新从文件服务器下载该文件（其他开发人员提交完整，个人项目更新后同步的情况）
				// 暂时默认文件服务中存在该文件，下载保存默认成功
				CommonUtil.downloadFileToLocal(clzFullName);
				// 进行编译
				loader.compiler(clzFullName);
				// 设置缓存
				redisUtil.set(clzRedisName, String.valueOf(CommonUtil.CLASS_BYTES.get(clzFullName).length));
				// 类加载
				clazz = loader.getClass(clzFullName);
			}
			Object instance = clazz.newInstance();
			Method mt = clazz.getDeclaredMethod(method, HttpServletRequest.class, HttpServletResponse.class);
			Object result = mt.invoke(instance, request, response);
			return Result.OK(result);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return Result.error("操作失败");
	}

	@PostMapping("/upload")
	public Result<?> upload(
			@RequestParam("clzName") String clzName,
			@RequestParam("file") MultipartFile file) {
		try {
			String clzFullName = "hot.form." + clzName;
			String clzRedisName = "hot:form:" + clzName;
			String serverPath = "hot/form/";
			String localPath = PathUtil.ROOT_PATH + serverPath;
			String orgName = file.getOriginalFilename();
			// 上传文件服务器
			fileServiceFeign.uploadFile("admin", serverPath, orgName, file);
			// 保存本地
			CommonUtil.saveFileToLocal(localPath, file);
			// 进行编译
			DeployLoader loader = DeployLoader.getInstance();
			loader.compiler(clzFullName);
			// 缓存信息 - 保存class文件的大小，与byte[] 相同长度
			int length = CommonUtil.CLASS_BYTES.get(clzFullName).length;
			// tools.jar 中无法使用redis工具，故此在这处理
			redisUtil.set(clzRedisName, String.valueOf(length));

			return Result.OK("上传成功");
		} catch (Exception e) {
			e.printStackTrace();
			return Result.error("上传失败");
		}
	}

}
